package thu.cs.segroup.agent.behaviour;

import java.net.MalformedURLException;
import java.net.URL;

import org.codehaus.xfire.client.Client;

import thu.cs.segroup.entity.TestTask;
import thu.cs.segroup.util.Constants;
import jade.core.behaviours.OneShotBehaviour;

public class RunnerExecuteWSTaskBehav extends OneShotBehaviour {

	private TestTask task;
	private int resultCount;
	
	public RunnerExecuteWSTaskBehav(TestTask _task) {
		task = _task;
		resultCount = 0;
	}
	
	@Override
	public void action() {
		for (int i = 0; i < task.getThreadCount(); i++) {
			WSTaskThread thread = new WSTaskThread(task, i, this);
			thread.run();
		}
	}
	
	public synchronized void addResult() {
		resultCount = resultCount + 1;
		if (resultCount == task.getThreadCount()) {
			System.out.println("TEST OVER from " + myAgent.getLocalName());
		}
	}
	
	public String getAgentName() {
		return myAgent.getLocalName();
	}
	
}

class WSTaskThread extends Thread {
	
	private TestTask tCase;
	private int seq;
	private RunnerExecuteWSTaskBehav parent;
	
	public WSTaskThread(TestTask _case, int _seq, RunnerExecuteWSTaskBehav _parent) {
		tCase = _case;
		seq = _seq;
		parent = _parent;
	}

	@Override
	public void run() {
		System.out.println("Thread " + seq + " is running.");
		
		// begin to test the WS
		try {
			Client client = new Client(new URL(tCase.getWsdlURL()));
			long startTime = System.nanoTime();
			Object[] result = client.invoke(tCase.getMethodName(), getInput(tCase.getInputTypes()));
			long endTime = System.nanoTime();
			long timeCost = endTime - startTime;
			
			if (result[0] == null ) {
				System.out.println("Result from " + parent.getAgentName() + ": " + "NULL");
			} else {
				System.out.println("Result from " + parent.getAgentName() + ": "+ result[0]);
			}
			
			parent.addResult();
			
		} catch (MalformedURLException e) {
			
		} catch (Exception e) {
			
		}
		
	}
	
	private Object[] getInput(String inputs) {
		String arr[] = inputs.split("[)]-");
		Object[] inputArr = new Object[arr.length];
		String type;
		String value;
		for (int i = 0;i < arr.length; i++) {
			int index = arr[i].indexOf('(');
			type = arr[i].substring(0, index);
			if (i != arr.length - 1) {
				value = arr[i].substring(index + 1, arr[i].length());
			} 
			else {
				value = arr[i].substring(index + 1, arr[i].length() - 1);
			}
			if (type.equals("STRING")) {
				inputArr[i] = new String(value);
			}
			else if (type.equals("FLOAT")) {
				inputArr[i] = new Float(value);
			}
			else if (type.equals("INT")) {
				inputArr[i] = new Integer(value);
			}
			else if (type.equals("BOOLEAN")) {
				if (value.equals("true")) {
					inputArr[i] = java.lang.Boolean.TRUE;
				}
				else if (value.equals("false")) {
					inputArr[i] = java.lang.Boolean.FALSE;
				}
			}
		}
		return inputArr;
	}
	
	private int getReturnType(String returnTypeName) {
		if (returnTypeName.equals("java.lang.Integer")) {
			return Constants.INT;
		}
		else if (returnTypeName.equals("java.lang.Float")) {
			return Constants.FLOAT;
		}
		else if (returnTypeName.equals("java.lang.Double")) {
			return Constants.DOUBLE;
		}
		else if (returnTypeName.equals("java.lang.Long")) {
			return Constants.LONG;
		}
		else if (returnTypeName.equals("java.lang.Short")) {
			return Constants.SHORT;
		}
		else if (returnTypeName.equals("java.lang.Byte")) {
			return Constants.BYTE;
		}
		else if (returnTypeName.equals("java.lang.String")) {
			return Constants.STRING;
		}
		else if (returnTypeName.equals("java.lang.Character")) {
			return Constants.CHARACTER;
		}
		else if (returnTypeName.equals("java.lang.Boolean")) {
			return Constants.BOOLEAN;
		}
		return Constants.ERROR;
	}
	
}